package jmars.mobile.domain.markov;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class State {
	private static Map<String, State> pool=new HashMap<String,State>();
	private String bts;
	private Long time;
	private int count=0;
	private Map<State,Integer> outCount=new HashMap<State,Integer>();
	private Map<State,Integer> inCount=new HashMap<State,Integer>();
	private volatile static int linkSize=0;
	private static Set<String> btsPool=new HashSet<String>();
	private static Set<Long> timePool=new HashSet<Long>();
	
	
	public static void init(int maxCapacity,float loadFactor){
		pool=new HashMap<String,State>(maxCapacity,loadFactor);
	}
	public static int stateSize(){
		return pool.size();
	}
	public static int linkSize(){
		return linkSize;
	}
	private State(){
		
	}
	
	private static String key(String bts,Long time){
		return bts+"-"+time;
	}
	public String getKey(){
		return key(bts,time);
	}
	public static State getState(String bts,Long time){
		return pool.get(key(bts,time));
	}
	public static State createInstance(String bts,Long time){
		State s = pool.get(key(bts,time));
		if(!btsPool.contains(bts))btsPool.add(bts);
		if(!timePool.contains(time))timePool.add(time);
		if(s==null){
			s=new State();
			s.setBts(bts);
			s.setTime(time);
			pool.put(s.getKey(), s);
			return s;
		}else
			return s;
	}
	public static void addLink(State from, State to){
		if(from.outCount.containsKey(to))
			from.outCount.put(to, from.outCount.get(to)+1);
		else
			from.outCount.put(to, 1);
		if(to.inCount.containsKey(from))
			to.inCount.put(from, to.inCount.get(from)+1);
		else
			to.inCount.put(to, 1);
		linkSize++;
	}
	public int getOutLink(String bts,Long time){
		if(this.outCount.get(State.getState(bts, time))==null)
			return 0;
		else
			return this.outCount.get(State.getState(bts, time));
	}
	@Override
	public boolean equals(Object s){
		if(s instanceof State)
			if(bts.equals(((State)s).getBts())&&time.equals(((State)s).time))return true;
		return false;
	}
	
	@Override
	public int hashCode(){
		return (bts+time).hashCode();
	}
	public String getBts() {
		return bts;
	}
	public void setBts(String bts) {
		this.bts = bts;
	}
	public Long getTime() {
		return time;
	}
	public void setTime(Long time) {
		this.time = time;
	}
	public static Set<String> getBtsPool() {
		return btsPool;
	}
	public static List<Long> getTimes(){
		ArrayList<Long> l = new ArrayList<Long>(timePool);    

        Collections.sort(l, new Comparator<Long>() {
            public int compare(Long o1, Long o2) {
                return o2==o1?0:(o2<o1?1:-1);
            }
        });
        
        return l;
	}
	public int getCount() {
		return count;
	}
	public int addCount(int c){
		count+=c;
		return count;
	}
}
